package com.tanjie.blackbean.web.support;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.method.HandlerMethod;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author: tanjie
 * @date: 2022-04-07
 **/
@Slf4j
public abstract class AnnotationExtractor {

    private AnnotationExtractor() {
    }

    /**
     * 查询handler方法上或handler所在类上的注解
     *
     * @param handlerMethod 接口请求处理方法
     * @param tClass        想要获取的目标注解类类型
     * @param <T>           返回的注解类型
     * @return 想要得到的注解实例
     */
    public static <T extends Annotation> T get(HandlerMethod handlerMethod, Class<T> tClass) {
        if (handlerMethod == null) {
            return null;
        }
        // 方法上的注解优先返回
        T methodAnnotation = handlerMethod.getMethodAnnotation(tClass);
        if (methodAnnotation != null) {
            return methodAnnotation;
        }
        Class<?> declaringClass = handlerMethod.getMethod().getDeclaringClass();
        return declaringClass.getAnnotation(tClass);
    }


    public static <T extends Annotation> T get(MethodParameter returnType, Class<T> tClass) {
        String methodName = Objects.requireNonNull(returnType.getMethod()).getName();
        // 方法上标注的注解优先
        if (returnType.hasMethodAnnotation(tClass)) {
            //log.debug("{}，从handler方法上获取到注解WrapResponse", methodName);
            return returnType.getMethodAnnotation(tClass);
        }
        // 获取直接标注的注解
        Class<?> declaringClass = returnType.getDeclaringClass();
        if (declaringClass.isAnnotationPresent(tClass)) {
            //log.debug("{}，从类上获取到直接标注的注解WrapResponse", methodName);
            return declaringClass.getAnnotation(tClass);
        }
        // 获取合并注解中的注解
        T t = AnnotatedElementUtils.findMergedAnnotation(declaringClass, tClass);
        if (t != null) {
            //log.debug("{}，从类上获取到合成注解中的WrapResponse", methodName);
            return t;
        }
        return null;
    }

    public static <T extends Annotation> T get(JoinPoint joinPoint, Class<T> tClass) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        if (method.isAnnotationPresent(tClass)) {
            return method.getAnnotation(tClass);
        }
        Class<?> targetClass = joinPoint.getTarget().getClass();
        if (targetClass.isAnnotationPresent(tClass)) {
            return targetClass.getAnnotation(tClass);
        }
        return AnnotatedElementUtils.findMergedAnnotation(targetClass, tClass);
    }


}
